package com.lumlord.common.database.config;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.SqlUtilConfig;
import com.lumlord.common.database.DBContextHolder;
import com.lumlord.common.database.DynamicDataSource;
import com.lumlord.common.mybatis.SqlInterceptor;
import com.main.Application;

import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

/**
 * @author GPF
 * @date 2020/05/06
 *  数据源（伪）工厂<br/>
 *  设置数据源
 */
@Configuration
@MapperScan(sqlSessionFactoryRef = "sessionFactory", basePackages = Application.PACKAGE)
public class DataSourceFactory {
	
	/**
	 * 返回 [MasterDb] 数据库的数据源
	 * 
	 * @return
	 */
	@Bean(name="masterDataSource")
	@Primary // 主数据源
	 public DataSource masterDataSource(@Value("${lumlord.mysql.master.ippd}") String ippd,
			@Value("${lumlord.mysql.master.username}") String username,
			@Value("${lumlord.mysql.master.password}") String password) { 
		return druidConfig.druidDataSource(ippd, username,password);
	}
	/*
	 * 从库节点 库 1  STEP 1  注册数据源
	 */
	@Bean(name="slaver1DbDataSource")
	 public DataSource slaver1DbDataSource(@Value("${lumlord.mysql.slaver1.ippd}") String ippd,
			@Value("${lumlord.mysql.slaver1.username}") String username,
			@Value("${lumlord.mysql.slaver1.password}") String password) { 
		return druidConfig.druidDataSource(ippd, username,password);
	}
	
	
	/** STEP 2  注入动态数据源
	 * @Primary 该注解表示在同一个接口有多个实现类可以注入的时候，默认选择哪一个，而不是让@autowire注解报错
	 * @Qualifier 根据名称进行注入，通常是在具有相同的多个类型的实例的一个注入（例如有多个DataSource类型的实例）
	 */
	@Bean("dynamicDataSource")
	public DynamicDataSource dataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
			@Qualifier("slaver1DbDataSource") DataSource slaver1DbDataSource
			) {
		Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
		targetDataSources.put(DBContextHolder.DBTypeEnum.MASTER, masterDataSource);
		targetDataSources.put(DBContextHolder.DBTypeEnum.SLAVE1, slaver1DbDataSource);
		
		DynamicDataSource dataSource = new DynamicDataSource();
		dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法
		dataSource.setDefaultTargetDataSource(targetDataSources.get(DBContextHolder.DBTypeEnum.MASTER));// 默认的datasource设

		return dataSource;
	}

	/**
	 * 配置事务管理器
	 */
	@Bean(name="transactionManager")
	public DataSourceTransactionManager transactionManager(@Qualifier("dynamicDataSource")DynamicDataSource  dataSource) throws Exception {
		return new DataSourceTransactionManager(dataSource);
	}
	
	@Bean(name = "sessionFactory")
	@Primary
	public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource)
			throws Exception {
		final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
		sessionFactory.setDataSource(dataSource);
		sessionFactory.setMapperLocations(
				new PathMatchingResourcePatternResolver().getResources(Application.MAPPER_LOCATION));
		sessionFactory.setTypeAliasesPackage(Application.DOMAIN_PACKAGE);
		sessionFactory.setVfs(SpringBootVFS.class); // 关键，将vfs设置为SpringBootVFS
		// mybatis 数据库字段与实体类属性驼峰映射配置
		sessionFactory.setPlugins(new Interceptor[] {new SqlInterceptor(),getPage()});
		 
		sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
		return sessionFactory.getObject();
	}
	
	
	@Bean(name = "jdbcTemplate")
	@Primary
	public JdbcTemplate jdbcTemplate(DynamicDataSource dataSource) {
	 return new JdbcTemplate(dataSource);
	}

	
	@Bean(name =  "sqlSessionTemplate")
	@Primary
	public SqlSessionTemplate sqlSessionTemplate(
			@Qualifier( "sessionFactory") SqlSessionFactory sessionFactory) throws Exception {
		return new SqlSessionTemplate(sessionFactory);
	}

	
	/**
	 * 設置 分頁插件
	 * @return
	 */
	private PageHelper getPage() {
		PageHelper pagehelper = new PageHelper();
		
		SqlUtilConfig sqlUtilConfig = new SqlUtilConfig();
		sqlUtilConfig.setReasonable(true);
		sqlUtilConfig.setSupportMethodsArguments(true);
		sqlUtilConfig.setParams("countSql");
		sqlUtilConfig.setDialect("mysql");
		pagehelper.setSqlUtilConfig(sqlUtilConfig);
		return pagehelper;
	}
	
	
	/////////////////////////

	@Autowired
	private DruidConfig druidConfig;

	 

}
